Import minib3d
Import cal3d


Class Cal3dB3dAnimation

	Field filename:String
	Field name:String
	Field isloaded:Bool = False
	Field id:int
	Field canim:CalCoreAnimation
	Field parent:Cal3dB3d
	
End Class


Class Cal3dB3dImage

	Field calim:CalImage
	Field filename:String
	Field name:String
	Field isloaded:Bool = False
	Field id:int

End Class

Class Cal3dB3dMaterial

	Field B3dBrush:TBrush
	Field Cmat:CalCoreMaterial
	Field matid:Int
	Field isloaded:Bool = False
	Field filename:String
	Field name:String
	Field maps:List<Cal3dB3dImage>
	
	
	
	Method New()
		B3dBrush = TBrush.CreateBrush(255,255,255)
		maps = New List<Cal3dB3dImage>
		matid = -1
	end

	Method New(id:Int,cm:CalCoreMaterial)
		B3dBrush = TBrush.CreateBrush(255,255,255)
		Cmat = cm
		maps = New List<Cal3dB3dImage>
		matid = id
	end

	Method New(r:Int,g:Int,b:Int,id:Int,cm:CalCoreMaterial)
		B3dBrush = TBrush.CreateBrush(r,g,b)
		Cmat = cm
		maps = New List<Cal3dB3dImage>
		matid = id
	end

	Method New(col:CalColor,id:Int,cm:CalCoreMaterial)
		B3dBrush = TBrush.CreateBrush(col.red,col.green,col.blue)
		Cmat = cm
		maps = New List<Cal3dB3dImage>
		matid = id
	end

End Class

Class Cal3dB3dMesh

	Field B3dMesh:TMesh
	Field CMesh:CalCoreMesh
	Field MID:Int
	Field surf:TSurface[] = New TSurface[0]
	Field filename:String
	Field name:String
	Field isloaded:Bool = false
	Field parent:Cal3dB3d
	
	Method PaintMaterial(ii:Int,brush:TBrush)
		'Print "Painting Surface"
		surf[ii].PaintSurface(brush)		
	
	End
	
	
	Method Build:Bool(v:Float[],f:Int[])
		
		If CMesh = Null 
			Print "Cmesh was null!"
			Return False
			
		Endif
		If B3dMesh = Null Then
			B3dMesh = TMesh.CreateMesh(parent.B3dModel)
			B3dMesh.anim = 2				
		Endif
		Local ind:Int = surf.Length()
		surf = surf.Resize(surf.Length()+1)
		
		surf[ind] = B3dMesh.CreateSurface()
		Print "Build: "+ind

		
		For Local i:Int = 0 To v.Length()-1 Step 3
			surf[ind].AddVertex(v[i],v[i+1],v[i+2])
		Next
		surf[ind].AddTriangle(f)

		surf[ind].UpdateNormals()
		isloaded = True
		Return True
	End Method


	Method Build:Bool(ind:Int,v:Float[],f:Int[])
		
		If CMesh = Null 
			Print "Cmesh was null!"
			Return False
			
		Endif
		If B3dMesh = Null Then
			B3dMesh = TMesh.CreateMesh(parent.B3dModel)
			B3dMesh.anim = 2				
		Endif
		If ind > surf.Length()-1 Then
			surf = surf.Resize(surf.Length()+1)
		
			surf[ind] = B3dMesh.CreateSurface()
			Print "Build: "+ind
		Else
			surf[ind].ClearSurface(True,True)
			Print "ReBuild: "+ind	
		Endif
		
		For Local i:Int = 0 To v.Length()-1 Step 3
			surf[ind].AddVertex(v[i],v[i+1],v[i+2])
		Next
		surf[ind].AddTriangle(f)

		surf[ind].UpdateNormals()
		isloaded = True
		Return True
	End Method


	Method Update(si:Int,v:Float[],f:Int[])
		surf[si].ClearSurface(True,True)

		For Local i:Int = 0 To v.Length()-1 Step 8
			Local vid:Int = surf[si].AddVertex(v[i],v[i+1],v[i+2])
			surf[si].VertexNormal(vid,v[i+3],v[i+4],v[i+5])
			surf[si].VertexTexCoords(vid,v[i+6],v[i+7])
		Next
		
		surf[si].AddTriangle(f)

	End
	
	Method Update(si:Int,v:Float[],t:Float[],f:int[])
		surf[si].ClearSurface(True,True)

		For Local i:Int = 0 To v.Length()-1 Step 3
			Local vid:Int = surf[si].AddVertex(v[i],v[i+1],-v[i+2])
			surf[si].VertexNormal(vid,v[i+3],v[i+4],-v[i+5])
			'surf[si].VertexTexCoords(vid,t[i],t[i+1])
		Next
		
		surf[si].AddTriangle(f)

	End
	
	


End

Class Cal3dB3d

	Field Skele:CalCoreSkeleton
	Field CoreModel:CalCoreModel
	Field Meshes:List<Cal3dB3dMesh>
	Field Materials:List<Cal3dB3dMaterial>
	Field Anims:List<Cal3dB3dAnimation>
	Field CModel:CalModel
	Field B3dModel:TMesh
	Field cal_renderer:CalRenderer
	Field isloaded:Bool = False
	Field rebuild:Bool = False
	Field SkeletonLoaded:Bool = False
	Field isanim:Bool = False
	Field SkeleFile:String
	Field SkeleName:String
	
	Field MeshFileList:StringList
	
	
	
	
	
	Method New()
		
		B3dModel = TMesh.CreateMesh()
		Meshes = New List<Cal3dB3dMesh>
		Anims = New List<Cal3dB3dAnimation>
		Materials = New List<Cal3dB3dMaterial>
		CoreModel = New CalCoreModel
		MeshFileList = New StringList
	End
	
	Method SetSkeleton(skel:CalCoreSkeleton)
		Skele = skel
		CoreModel.setCoreSkeleton(Skele)

	End
	
	
	Method AddAnim:Cal3dB3dAnimation(anm:CalCoreAnimation)
		'If Skele = Null Then Return


		If anm <> Null Then
			Local c3db3da:Cal3dB3dAnimation = New Cal3dB3dAnimation()
			c3db3da.id = CoreModel.addCoreAnimation(anm)
			c3db3da.parent = Self
			Anims.AddLast(c3db3da)
			Return c3db3da
		Endif
		Return Null
		
	End

	Method AddAnim:Cal3dB3dAnimation(file:String,name:String="anim")
	
		Local c3db3da:Cal3dB3dAnimation = New Cal3dB3dAnimation()
		c3db3da.filename = file
		c3db3da.name = name
		c3db3da.parent = Self
		Anims.AddLast(c3db3da)
		Return c3db3da		
	End
	
	Method UpdateMaterial(cmat:CalCoreMaterial,mat:Cal3dB3dMaterial,uri:String="")
	
		CoreModel.addCoreMaterial(cmat)
		
		For Local i:Int = 0 To cmat.getMapCount()-1
			Local cimg:Cal3dB3dImage = New Cal3dB3dImage
			cimg.id = i
			
			Local fname:String = cmat.getMapFilename(i)
			Local nfname:String[] = fname.Split(".")
			fname = fname.Replace("."+nfname[nfname.Length-1],"")
			Print "Fetch: "+fname
			cimg.filename = uri+fname
			'Print "Get "+
			cimg.name = cmat.getMapFilename(i)
			mat.maps.AddLast(cimg)
		Next
		mat.isloaded = True
	
	End
	
	Method GetMaterial:Cal3dB3dMaterial(index:int)
	
		For Local mat:Cal3dB3dMaterial = Eachin Materials
		
			If mat.matid = index Then

				'If mat.isloaded = True Then
					'if material is loaded then assign the material to our b3d surface
				'	PaintMaterial(ii:Int,brush:TBrush)
				'Endif
				
				Return mat
				
			Endif
		
		Next
			
		Return Null
	
	End
	
	Method AddMesh:Cal3dB3dMesh(msh:CalCoreMesh)
	

		If msh <> Null Then
			
			Local c3db3dm:Cal3dB3dMesh = New Cal3dB3dMesh()
			c3db3dm.MID = CoreModel.addCoreMesh(msh)
			Print "Added: "+c3db3dm.MID
			c3db3dm.CMesh = msh
			c3db3dm.B3dMesh = TMesh.CreateMesh(B3dModel)
			c3db3dm.B3dMesh.anim = 2
			c3db3dm.parent = Self
			
			'iterate through submeshes to retrieve material ids
			For Local i:Int = 0 To c3db3dm.CMesh.getCoreSubmeshCount()-1
			
				Local smesh:CalCoreSubmesh = c3db3dm.CMesh.getCoreSubmesh(i)
				If smesh <> Null Then
				
					Local matid:Int = smesh.getCoreMaterialThreadId()
					'see if we have the id
					Local haveid:Bool = False
					For Local mat:Cal3dB3dMaterial = Eachin Materials
					
						If mat.matid = matid Then
							haveid = True
							Exit
						Endif
					
					Next
					If haveid = False Then
						Local cmat:Cal3dB3dMaterial = New Cal3dB3dMaterial
						cmat.matid = matid
						Materials.AddLast(cmat)
					Endif
				
				Endif
			
			Next
			
			Meshes.AddLast(c3db3dm)
			Return c3db3dm
		Endif
		Return null
	End
	
	
	
	Method AddMesh:Cal3dB3dMesh(file:String,name:String="mesh")
	
		Local c3db3dm:Cal3dB3dMesh = New Cal3dB3dMesh()
		c3db3dm.filename = file
		c3db3dm.name = name
		c3db3dm.parent = Self
		Meshes.AddLast(c3db3dm)
		Return c3db3dm
	End


	
	Method Build()
		If CoreModel.getCoreSkeleton() = Null Then
			Print "Core Skeleton is null!"
		Endif
		CoreModel.getCoreSkeleton().calculateBoundingBoxes(CoreModel)
		
		For Local mat:Cal3dB3dMaterial = Eachin Materials
			'Haxx...
			CoreModel.createCoreMaterialThread(mat.matid)
			CoreModel.setCoreMaterialId(mat.matid, 0, mat.matid)		
		Next			
		CModel = CoreModel.makemodel()
		
		For Local cb3d:Cal3dB3dMesh = Eachin Meshes
			CModel.attachMesh(cb3d.MID)
		Next
		
	
		
		'For Local anm:CalCoreAnimation = Eachin Anims
		'	CModel.
		'Next
		If CModel <> Null Then
			Print "Have Cmodel"
		Endif
		If isanim = True then
			CModel.getMixer().blendCycle(0,1,0)
		Endif
		cal_renderer = CModel.getRenderer()
		cal_renderer.beginRendering()
			
		Local mc:Int = cal_renderer.getMeshCount()	
		Print "Mesh Count: "+mc
		For Local i:Int = 0 To mc	
			
			For Local cb3d:Cal3dB3dMesh = Eachin Meshes
				'If cb3d.B3dMesh <> Null Then cb3d.B3dMesh.FreeEntity()
				'cb3d.B3dMesh = TMesh.CreateMesh(B3dModel)
				'cb3d.B3dMesh.anim = 2	
				If cb3d.MID = i Then
					Print "Got Mesh: "+i
					'cal_renderer.selectMeshSubmesh(mc,i)
					Local submeshCount:Int = cal_renderer.getSubmeshCount(i)
					Print "NOF: Submeshes "+submeshCount
					'cb3d.surf = New TSurface[0]
					For Local ii:Int = 0 To submeshCount-1
					
						cal_renderer.selectMeshSubmesh(cb3d.MID,ii)
						
						Local vertexCount:Int = cal_renderer.getVertexCount()
						Local faceCount:Int = cal_renderer.getFaceCount()
						
						Print "Verts: "+vertexCount+" Faces"+faceCount
						


						Local faces:Int[] = New Int[faceCount*3]
						Local vertices:Float[] = New Float[vertexCount*3]						
						cal_renderer.getVertices(vertices)	
						cal_renderer.getFaces(faces)
						cb3d.Build(ii,vertices,faces)
						Local smesh:CalSubmesh = CModel.getMesh(cb3d.MID).getSubmesh(ii)
						Local brush:Cal3dB3dMaterial = GetMaterial(smesh.getCoreMaterialId)
						If brush <> Null then
							cb3d.PaintMaterial(ii,brush.B3dBrush)
						Endif
						
						
										
						
					Next
					

					
				
				
				Endif
			
			Next
		
		Next
		cal_renderer.endRendering()
		
	
	End




	Method UpdateAnimation(anim:Cal3dB3dAnimation,anm:CalCoreAnimation)
	
		anim.id = CoreModel.addCoreAnimation(anm)
		anim.isloaded = True
		isloaded = False
		isanim = true
	
	End


	Method UpdateMesh(file:String,msh:CalCoreMesh)
	
		For Local cb3d:Cal3dB3dMesh = Eachin Meshes
		
			If cb3d.filename = file Then
				cb3d.MID = CoreModel.addCoreMesh(msh)
				If cb3d.B3dMesh = Null Then cb3d.B3dMesh = TMesh.CreateMesh(B3dModel)
				cb3d.B3dMesh.anim = 2
				cb3d.parent = Self	
				cb3d.isloaded = True
				cb3d.CMesh = msh
				'rebuild = true	
				
				
				For Local i:Int = 0 To cb3d.CMesh.getCoreSubmeshCount()-1
				
					Local smesh:CalCoreSubmesh = cb3d.CMesh.getCoreSubmesh(i)
					If smesh <> Null Then
					
						Local matid:Int = smesh.getCoreMaterialThreadId()
						'see if we have the id
						Local haveid:Bool = False
						For Local mat:Cal3dB3dMaterial = Eachin Materials
						
							If mat.matid = matid Then
								haveid = True
								Exit
							Endif
						
						Next
						If haveid = False Then
							Local cmat:Cal3dB3dMaterial = New Cal3dB3dMaterial
							cmat.matid = matid
							Materials.AddLast(cmat)
						Endif
					
					Endif
				
				Next				
						
			Endif
		Next		
	
	End

	Method MeshesLoaded:Bool()
		For Local cb3d:Cal3dB3dMesh = Eachin Meshes
		
			If cb3d.isloaded = False Then Return False
		Next
		Return true
	End

	Method Update:Int(d:Float)
		If isloaded = True Then
			'If rebuild = True Then
			'	Build()
			'	rebuild = False
			'Endif
			CModel.update(d)
			cal_renderer.beginRendering()
				Local mc:Int = cal_renderer.getMeshCount()
				For Local i:Int = 0 To mc	
					For Local cb3d:Cal3dB3dMesh = Eachin Meshes
						If cb3d.MID = i Then
							Local submeshCount:Int = cal_renderer.getSubmeshCount(i)
							
							For Local ii:Int = 0 To submeshCount-1
								cal_renderer.selectMeshSubmesh(cb3d.MID,ii)
								'Local vertexCount:Int = cal_renderer.getVertexCount()
								'Local faceCount:Int = cal_renderer.getFaceCount()
	
								
								'Local vertices:Float[] = New Float[vertexCount*8]
								'Local texcoords:Float[] = New Float[vertexCount*3]
								'Local faces:Int[] = New Int[faceCount*3]							
								
								'cal_renderer.getVerticesNormalsAndTexCoords(vertices)
								'cal_renderer.getFaces(faces)
								'cb3d.Update(ii,vertices,faces)
								'Print "Rendering "+ii
								B3DgetVerticesNormalsAndTexCoords(cal_renderer,cb3d.surf[ii].vert_data)
								cb3d.surf[ii].reset_vbo = -1
								Local smesh:CalCoreSubmesh = CoreModel.getCoreMesh(cb3d.MID).getCoreSubmesh(ii)
							'	Print "Get Brush: "+smesh.getCoreMaterialThreadId()
								Local brush:Cal3dB3dMaterial = GetMaterial(smesh.getCoreMaterialThreadId())
								If brush <> Null then
									cb3d.PaintMaterial(ii,brush.B3dBrush)
								Endif								
								'Print "MAT: "+cal_renderer.m_selectedSubmesh.m_coreMaterialId
								'If cal_renderer.m_selectedSubmesh.m_coreMaterialId > -1 then
									'cal_renderer.getTextureCoordinates(0,texcoords,3)
								
									'cb3d.Update(ii,vertices,faces)
								'Else
									'cb3d.Update(ii,vertices,faces)
								'Endif
								'cb3d.surf[ii].ClearSurface(True,True,False)
								
								
							Next
						Endif
					Next
				Next
			cal_renderer.endRendering()
		Else
			'check skeleton
			
			If SkeletonLoaded = True And MeshesLoaded = True Then
				Build()
				
				isloaded = True
			Endif
		Endif
	End	

End





Function B3DgetVerticesNormalsAndTexCoords:Int(renderer:CalRenderer,vertexBuffer:VertexDataBuffer, numTexCoords:Int=1)
	
		' check if the submesh handles vertex data internally
		If renderer.m_selectedSubmesh.hasInternalData() = True Then
			' get the vertex vector of the submesh
			Local vectorVertex:CalVector[] = renderer.m_selectedSubmesh.getVectorVertex()
			' get the normal vector of the submesh
			Local vectorNormal:CalVector[] = renderer.m_selectedSubmesh.getVectorNormal()	
			' get the texture coordinate vector vector
			Local vectorvectorTextureCoordinate:CalTextureCoordinate[][] = renderer.m_selectedSubmesh.getCoreSubmesh().getVectorVectorTextureCoordinate()
	
			Local textureCoordinateCount:Int = vectorvectorTextureCoordinate.Length
	
			If numTexCoords < 0 Then
				numTexCoords = 1
			Endif
			' check if the given texture coordinate count is valid
			If numTexCoords < 0 Or numTexCoords > textureCoordinateCount Then
				If textureCoordinateCount <> 0 then
					Print "Invalid Texture Coord Count"
					Return -1
				Endif
			Endif
	
			' get the number of vertices in the submesh
			Local vertexCount:Int = renderer.m_selectedSubmesh.getVertexCount()
	
	
			If textureCoordinateCount = 0 then
				Local vi:Int = 0
				For Local vertexId:Int = 0 To vertexCount-1
					Local vertex:CalVector = vectorVertex[vertexId]
					Local normal:CalVector = vectorNormal[vertexId]
					vertexBuffer.PokeVertCoords(vertexId,vertex.x,vertex.y,-vertex.z)
					vertexBuffer.PokeNormals(vertexId,normal.x,normal.y,-normal.z)
				Next
			Else
				If numTexCoords = 1 Then
					Local vi:Int = 0
					For Local vertexId:Int = 0 To vertexCount-1
						Local vertex:CalVector= vectorVertex[vertexId]
						Local normal:CalVector = vectorNormal[vertexId]
						Local texCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[0][vertexId]
						vertexBuffer.PokeVertCoords(vertexId,vertex.x,vertex.y,-vertex.z)
						vertexBuffer.PokeNormals(vertexId,normal.x,normal.y,-normal.z)	
						vertexBuffer.PokeTexCoords0(vertexId,texCoord.u,texCoord.v)				
					Next
				Else
					Local vi:Int = 0
					For Local vertexId:Int = 0 To vertexCount-1
						Local vertex:CalVector = vectorVertex[vertexId]
						Local normal:CalVector = vectorNormal[vertexId]
						vertexBuffer.PokeVertCoords(vertexId,vertex.x,vertex.y,-vertex.z)
						vertexBuffer.PokeNormals(vertexId,normal.x,normal.y,-normal.z)	
						'vertexBuffer.PokeTexCoords0(vertexId,texCoord.u,texCoord.v)	
						Local txv:Int = 0	
						For Local mapId:Int = 0 To numTexCoords-1
							Local texCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[mapId][vertexId]
							If txv = 0 Then
								vertexBuffer.PokeTexCoords0(vertexId,texCoord.u,texCoord.v)
							Else
								vertexBuffer.PokeTexCoords1(vertexId,texCoord.u,texCoord.v)
							Endif
							'vertexBuffer[vi    ] = texCoord.u
							'vertexBuffer[vi + 1] = texCoord.v
							txv = txv + 1
							'vi += 2
						Next
					Next
				Endif		
			Endif
	
			Return vertexCount
		Endif
	
		' submesh does not handle the vertex data internally, so let the physique calculate it now
		Return B3DcalculateVerticesNormalsAndTexCoords(renderer.m_model.getPhysique(),renderer.m_selectedSubmesh, vertexBuffer, numTexCoords)	
	
End

Function B3DcalculateVerticesNormalsAndTexCoords:Int(phys:CalPhysique,submesh:CalSubmesh, vertexBuffer:VertexDataBuffer, numTexCoords:Int)
	
		If numTexCoords < 0 Then
			numTexCoords = 0
		Endif
		' get bone vector of the skeleton
		Local vectorBone:CalBone[] = phys.m_model.getSkeleton().getVectorBone()
	
		' get vertex vector of the submesh
		Local vectorVertex:CalVertex[] = submesh.getCoreSubmesh().getVectorVertex()
	
		' get the texture coordinate vector vector
		Local vectorvectorTextureCoordinate:CalTextureCoordinate[][] = submesh.getCoreSubmesh().getVectorVectorTextureCoordinate()
	
		Local textureCoordinateCount:Int = vectorvectorTextureCoordinate.Length
		'Print "NOF Texcoords: "+textureCoordinateCount
		' check if the given texture coord count is valid
		If numTexCoords < 0 Or numTexCoords > textureCoordinateCount Then
			If textureCoordinateCount <> 0 Then
				Return -1
			Endif
		Endif
	
		' get physical property vector of the core submesh
		Local vectorPhysicalProperty:CalPhysicalProperty[] = submesh.getCoreSubmesh().getVectorPhysicalProperty()
	
		' get the number of vertices
		Local vertexCount:Int = submesh.getVertexCount()
	
		' get the sub morph target vector from the core sub mesh
		Local vectorSubMorphTarget:CalCoreSubMorphTarget[] = submesh.getCoreSubmesh().getVectorCoreSubMorphTarget()
	
		' calculate the base weight
		Local baseWeight:Float = submesh.getBaseWeight()
	
		' get the number of morph targets
		Local morphTargetCount:Int = submesh.getMorphTargetWeightCount()
	
		' calculate all submesh vertices
		Local vi:Int = 0
		Local position:CalVector = New CalVector
		Local normal:CalVector = New CalVector
		For Local vertexId:Int = 0 To vertexCount-1
			' get the vertex
			Local vertex:CalVertex = vectorVertex[vertexId]
	
			' blend the morph targets
			position.assign(0, 0, 0)
			normal.assign(0, 0, 0)
			If baseWeight = 1 then
				position.x = vertex.position.x
				position.y = vertex.position.y
				position.z = vertex.position.z
				normal.x = vertex.normal.x
				normal.y = vertex.normal.y
				normal.z = vertex.normal.z
			Else
				position.x = baseWeight * vertex.position.x
				position.y = baseWeight * vertex.position.y
				position.z = baseWeight * vertex.position.z
				normal.x = baseWeight * vertex.normal.x
				normal.y = baseWeight * vertex.normal.y
				normal.z = baseWeight * vertex.normal.z
	
				For Local morphTargetId:Int = 0 To morphTargetCount-1
					Local blendVertex:CalBlendVertex = vectorSubMorphTarget[morphTargetId].getVectorBlendVertex()[vertexId]
					Local currentWeight:Float = submesh.getMorphTargetWeight(morphTargetId)
					position.x += currentWeight * blendVertex.position.x
					position.y += currentWeight * blendVertex.position.y
					position.z += currentWeight * blendVertex.position.z
					normal.x += currentWeight * blendVertex.normal.x
					normal.y += currentWeight * blendVertex.normal.y
					normal.z += currentWeight * blendVertex.normal.z
				Next
			Endif
	
			' initialize vertex
			Local x:Float, y:Float, z:Float
			x = 0
			y = 0
			z = 0
	
			' initialize normal
			Local nx:Float, ny:Float, nz:Float
			nx = 0
			ny = 0
			nz = 0
	
			' blend together all vertex influences
			Local influenceCount:Int = vertex.vectorInfluence.Length
			If influenceCount = 0 Then
				x = position.x
				y = position.y
				z = position.z
				nx = normal.x
				ny = normal.y
				nz = normal.z
			Else
				For Local influenceId:Int = 0 To influenceCount-1
					' get the influence
					Local influence:CalInfluence = vertex.vectorInfluence[influenceId]
	
					' get the bone of the influence vertex
					Local bone:CalBone = vectorBone[influence.boneId]
	
					' transform vertex with current state of the bone
					Local v:CalVector = New CalVector(position)
					v.multMatrixLocal(bone.getTransformMatrix())
					v.addLocal(bone.getTranslationBoneSpace())
	
					x += influence.weight * v.x
					y += influence.weight * v.y
					z += influence.weight * v.z
	
					' transform normal with current state of the bone
					Local n:CalVector = New CalVector(normal)
					n.multMatrixLocal(bone.getTransformMatrix())
	
					nx += influence.weight * n.x
					ny += influence.weight * n.y
					nz += influence.weight * n.z
				Next
			Endif
	
			' save vertex position
			If submesh.getCoreSubmesh().getSpringCount() > 0 And submesh.hasInternalData() = True Then
				' get the pgysical property of the vertex
				Local physicalProperty:CalPhysicalProperty = vectorPhysicalProperty[vertexId]
	
				' assign new vertex position if there is no vertex weight
				If physicalProperty.weight = 0 Then
					'vertexBuffer[vi    ] = x * m_axisFactorX
					'vertexBuffer[vi + 1] = y * m_axisFactorY
					'vertexBuffer[vi + 2] = z * m_axisFactorZ
					vertexBuffer.PokeVertCoords(vertexId,x * phys.m_axisFactorX,y * phys.m_axisFactorY,-(z * phys.m_axisFactorZ))
					'vertexBuffer.PokeNormals(vertexId,normal.x,normal.y,normal.z)	
					'vertexBuffer.PokeTexCoords0(vertexId,texCoord.u,texCoord.v)						
				Endif
			Else
				'vertexBuffer[vi    ] = x * m_axisFactorX
				'vertexBuffer[vi + 1] = y * m_axisFactorY
				'vertexBuffer[vi + 2] = z * m_axisFactorZ
				vertexBuffer.PokeVertCoords(vertexId,x * phys.m_axisFactorX,y * phys.m_axisFactorY,-(z * phys.m_axisFactorZ))
			Endif
	
			' re-normalize normal if necessary
			If phys.m_normalize = True Then
				nx /= phys.m_axisFactorX
				ny /= phys.m_axisFactorY
				nz /= phys.m_axisFactorZ
	
				Local scale:Float = 1 / Sqrt(nx * nx + ny * ny + nz * nz)
	
				'vertexBuffer[vi + 3] = nx * scale
				'vertexBuffer[vi + 4] = ny * scale
				'vertexBuffer[vi + 5] = nz * scale
				vertexBuffer.PokeNormals(vertexId,nx * scale,ny * scale,-(nz * scale))
			Else
				'vertexBuffer[vi + 3] = nx
				'vertexBuffer[vi + 4] = ny
				'vertexBuffer[vi + 5] = nz
				vertexBuffer.PokeNormals(vertexId,nx,ny,-nz)
			Endif
	
			'vi = vi + 6
	
			If textureCoordinateCount = 0 Then
				vi = vi + numTexCoords * 2
			Else
				For Local mapId:Int = 0 To numTexCoords-1
					Local textureCoord:CalTextureCoordinate = vectorvectorTextureCoordinate[mapId][vertexId]
					If mapId = 0 Then
						vertexBuffer.PokeTexCoords0(vertexId,textureCoord.u,textureCoord.v)
					Else
						vertexBuffer.PokeTexCoords1(vertexId,textureCoord.u,textureCoord.v)
					Endif
					'vertexBuffer[vi    ] = textureCoord.u
					'vertexBuffer[vi + 1] = textureCoord.v
	
					'vi = vi + 2
				Next
			Endif
		Next
	
		Return vertexCount	
	
	End